import { ref } from 'vue'
import { ElMessage, ElNotification } from 'element-plus'

interface WebSocketMessage {
  type: string
  content: string
  timestamp: string
  [key: string]: any
}

export class WebSocketService {
  private static instance: WebSocketService
  private socket: WebSocket | null = null
  private reconnectAttempts = 0
  private maxReconnectAttempts = 5
  private reconnectInterval = 3000 // 3秒
  private url = ''
  private isConnecting = false
  private storageKey = 'websocket_messages'

  // 消息列表
  public messages = ref<WebSocketMessage[]>([])
  // 连接状态
  public connected = ref(false)
  // 新消息标志
  public hasNewMessage = ref(false)

  private constructor() {
    // 从本地存储加载消息
    this.loadMessages()
  }

  /**
   * 获取WebSocketService单例
   */
  public static getInstance(): WebSocketService {
    if (!WebSocketService.instance) {
      WebSocketService.instance = new WebSocketService()
    }
    return WebSocketService.instance
  }

  /**
   * 连接WebSocket服务器
   * @param role 角色 (user/doctor)
   * @param id 用户ID
   */
  public connect(role: string, id: string | number): void {
    if (this.socket && (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING)) {
      console.log('WebSocket已连接或正在连接中')
      return
    }

    if (this.isConnecting) {
      console.log('WebSocket正在连接中')
      return
    }

    this.isConnecting = true
    this.url = `ws://localhost:8080/ws/${role}/${id}`

    try {
      this.socket = new WebSocket(this.url)

      this.socket.onopen = this.onOpen.bind(this)
      this.socket.onmessage = this.onMessage.bind(this)
      this.socket.onclose = this.onClose.bind(this)
      this.socket.onerror = this.onError.bind(this)
    } catch (error) {
      console.error('WebSocket连接错误:', error)
      this.isConnecting = false
      this.attemptReconnect()
    }
  }

  /**
   * 断开WebSocket连接
   */
  public disconnect(): void {
    if (this.socket) {
      this.socket.close()
      this.socket = null
      this.connected.value = false
      console.log('WebSocket已断开连接')
    }
  }

  /**
   * 发送消息
   * @param message 消息内容
   */
  public sendMessage(message: any): void {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify(message))
    } else {
      console.error('WebSocket未连接，无法发送消息')
      ElMessage.error('消息发送失败，请检查网络连接')
    }
  }

  /**
   * WebSocket连接成功回调
   */
  private onOpen(event: Event): void {
    console.log('WebSocket连接成功')
    this.connected.value = true
    this.isConnecting = false
    this.reconnectAttempts = 0
  }

  /**
   * WebSocket接收消息回调
   */
  private onMessage(event: MessageEvent): void {
    try {
      let message: WebSocketMessage;
      const data = event.data;

      // 检查消息是否以"Message(id"开头（非JSON格式）
      if (typeof data === 'string' && data.startsWith('Message(id')) {
        // 自定义解析逻辑处理非JSON格式消息
        console.log('收到非JSON格式WebSocket消息:', data);

        // 尝试从消息中提取内容
        // 假设格式类似于 Message(id=123, content=Hello, type=chat, timestamp=2023-01-01)
        const contentMatch = data.match(/content=([^,\)]+)/);
        const typeMatch = data.match(/type=([^,\)]+)/);
        const timestampMatch = data.match(/timestamp=([^,\)]+)/);

        message = {
          type: typeMatch ? typeMatch[1] : 'unknown',
          content: contentMatch ? contentMatch[1] : data, // 如果无法提取内容，则使用原始消息
          timestamp: timestampMatch ? timestampMatch[1] : new Date().toISOString()
        };
      } else {
        // 尝试作为JSON解析
        message = JSON.parse(data) as WebSocketMessage;
      }

      console.log('处理后的WebSocket消息:', message);

      // 添加消息到列表
      this.messages.value.unshift(message);

      // 设置新消息标志
      this.hasNewMessage.value = true;

      // 保存消息到本地存储
      this.saveMessages();

      // 显示通知
      this.showNotification(message);
    } catch (error) {
      console.error('解析WebSocket消息出错:', error);

      // 即使解析失败，也尝试显示原始消息
      try {
        const fallbackMessage: WebSocketMessage = {
          type: 'unknown',
          content: typeof event.data === 'string' ? event.data : '收到无法解析的消息',
          timestamp: new Date().toISOString()
        };

        console.log('使用原始消息内容:', fallbackMessage);
        this.messages.value.unshift(fallbackMessage);
        this.hasNewMessage.value = true;
        this.saveMessages();
        this.showNotification(fallbackMessage);
      } catch (fallbackError) {
        console.error('无法显示原始消息:', fallbackError);
      }
    }
  }

  /**
   * WebSocket关闭连接回调
   */
  private onClose(event: CloseEvent): void {
    console.log('WebSocket连接关闭:', event)
    this.connected.value = false
    this.isConnecting = false

    // 尝试重新连接
    if (!event.wasClean) {
      this.attemptReconnect()
    }
  }

  /**
   * WebSocket错误回调
   */
  private onError(event: Event): void {
    console.error('WebSocket错误:', event)
    this.isConnecting = false
  }

  /**
   * 尝试重新连接
   */
  private attemptReconnect(): void {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.log('达到最大重连次数，停止重连')
      return
    }

    this.reconnectAttempts++
    console.log(`尝试重新连接 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`)

    setTimeout(() => {
      if (this.url) {
        const urlParts = this.url.split('/')
        const role = urlParts[urlParts.length - 2]
        const id = urlParts[urlParts.length - 1]
        this.connect(role, id)
      }
    }, this.reconnectInterval)
  }

  /**
   * 显示消息通知
   */
  private showNotification(message: WebSocketMessage): void {
    ElNotification({
      title: '新消息',
      message: message.content,
      type: 'info',
      duration: 3000
    })
  }

  /**
   * 清空消息列表
   */
  public clearMessages(): void {
    this.messages.value = []
    this.saveMessages()
  }

  /**
   * 保存消息到本地存储
   */
  private saveMessages(): void {
    try {
      localStorage.setItem(this.storageKey, JSON.stringify(this.messages.value))
    } catch (error) {
      console.error('保存消息到本地存储失败:', error)
    }
  }

  /**
   * 从本地存储加载消息
   */
  private loadMessages(): void {
    try {
      const savedMessages = localStorage.getItem(this.storageKey)
      if (savedMessages) {
        this.messages.value = JSON.parse(savedMessages)
      }
    } catch (error) {
      console.error('从本地存储加载消息失败:', error)
    }
  }

  /**
   * 重置新消息标志
   */
  public resetNewMessageFlag(): void {
    this.hasNewMessage.value = false
  }
}

// 导出WebSocketService单例
export const websocketService = WebSocketService.getInstance()
